//
// Created by 王乐 on 2022/2/9.
//

#include "LeParticleSystem.h"
#include "LeParticleGameObject.h"
#include "LeScene.h"
#include "LeUtils.h"

LeParticleSystem::~LeParticleSystem()
{

}

LeParticleSystem::LeParticleSystem(LeGameObject *pGameObject):
        m_pGameObject(pGameObject)
{
    numShadows = 0;
}

void LeParticleSystem::emitParticles(unsigned int num, LeParticle &particledef,
                                     glm::vec3 offset, glm::vec3 rangemin, glm::vec3 rangemax,
                                     glm::vec2 rotrange,
                                     glm::vec3 scalmin, glm::vec3 scalmax)
{
    glm::vec3 genPosition = m_pGameObject->m_Transform.m_Position + offset;
    glm::vec3 genRangeMin = genPosition + rangemin;
    glm::vec3 genRangeMax = genPosition + rangemax;
    float maxDist = glm::length(genRangeMax - genRangeMin) / 2;

    for(int i = 0; i < num; i++)
    {
        particledef.m_StartPosition = glm::vec3(LeMath::getRandomF(genRangeMin.x, genRangeMax.x),
                                                LeMath::getRandomF(genRangeMin.y, genRangeMax.y),
                                                LeMath::getRandomF(genRangeMin.z, genRangeMax.z));
        particledef.m_StartRotation = LeMath::getRandomF(rotrange.x, rotrange.y);
        particledef.m_StartScale = glm::vec3(LeMath::getRandomF(scalmin.x, scalmax.x),
                                             LeMath::getRandomF(scalmin.y, scalmax.y),
                                             LeMath::getRandomF(scalmin.z, scalmax.z));
        particledef.m_RValue = glm::length(particledef.m_StartPosition - genPosition) / maxDist;

        getParticleGameObject(particledef, particledef.m_RValue);
    }
}

LeParticleGameObject *LeParticleSystem::getParticleGameObject(LeParticle &particledef, float r)
{
    if(m_qParticleGameObjects.size() != 0)
    {
        LeParticleGameObject* pfirstobj = m_qParticleGameObjects.front();
        pfirstobj->setActive(true);
        pfirstobj->m_Transform.setPosition(particledef.m_StartPosition.x, particledef.m_StartPosition.y, particledef.m_StartPosition.z);
        pfirstobj->m_Transform.setRotation(0,0,particledef.m_StartRotation);
        pfirstobj->m_Transform.setScale(particledef.m_StartScale.x, particledef.m_StartScale.y, particledef.m_StartScale.z);
        pfirstobj->m_Particle = particledef;
        m_qParticleGameObjects.pop();
        return pfirstobj;
    }
    else
    {
        LeParticleGameObject *partcleobj = new LeParticleGameObject(this);
        partcleobj->InitializeParticleGameObject("/Users/wangle/CLionProjects/Leste/res/shader/simplepng.vs",
                                                 "/Users/wangle/CLionProjects/Leste/res/shader/simplepng.fs",particledef);
        partcleobj->setActive(true);
        LeScene::getInstance()->addGameObject(partcleobj);
        return partcleobj;
    }
}

void LeParticleSystem::returnParticleGameObject(LeParticleGameObject* pgameobj)
{
    pgameobj->setActive(false);
    m_qParticleGameObjects.push(pgameobj);
}

void LeParticleSystem::emitShadows(LeParticle &particledef)
{
    glm::vec3 genPosition = m_pGameObject->m_Transform.m_Position;

    particledef.m_StartPosition = genPosition;
    particledef.m_StartRotation = 0;

    getShadowGameObject(particledef);
}

LeParticleGameObject *LeParticleSystem::getShadowGameObject(LeParticle &particledef)
{
    if(m_qShadowGameObjects.size() != 0)
    {
        LeParticleGameObject* pfirstobj = m_qShadowGameObjects.front();
        pfirstobj->setActive(true);
        pfirstobj->m_Transform.setPosition(particledef.m_StartPosition.x, particledef.m_StartPosition.y, particledef.m_StartPosition.z);
        pfirstobj->m_Transform.setRotation(0,0,particledef.m_StartRotation);
        pfirstobj->m_Transform.setScale(particledef.m_StartScale.x, particledef.m_StartScale.y, particledef.m_StartScale.z);
        pfirstobj->m_Particle = particledef;
        m_qShadowGameObjects.pop();
        return pfirstobj;
    }
    else
    {
        LeParticleGameObject *partcleobj = new LeParticleGameObject(this);
        partcleobj->InitializeParticleGameObject("/Users/wangle/CLionProjects/Leste/res/shader/moveshadow.vs",
                                                 "/Users/wangle/CLionProjects/Leste/res/shader/moveshadow.fs",particledef);
        partcleobj->setActive(true);
        LeScene::getInstance()->addGameObject(partcleobj);
        return partcleobj;
    }
}

void LeParticleSystem::returnShadowGameObject(LeParticleGameObject *pgameobj)
{
    pgameobj->setActive(false);
    m_qShadowGameObjects.push(pgameobj);
}

int LeParticleSystem::getPoolNum()
{
    return m_qParticleGameObjects.size();
}
